import type { Directive, DirectiveBinding } from 'vue'

interface MoveOptions {
     // 是否启用拖拽
     enabled?: boolean
     // 拖拽结束回调函数
     onEnd?: (position: { left: number; top: number }) => void
     isBindChildDom?: boolean
}

const move: Directive = {
     mounted(
          el: HTMLElement,
          binding: DirectiveBinding<MoveOptions | boolean>,
     ) {
          let moveEl = el.firstElementChild as HTMLElement

          if (!moveEl) return
          // 解析指令参数
          const options: MoveOptions =
               typeof binding.value === 'boolean'
                    ? { enabled: binding.value }
                    : binding.value || {}

          const { enabled = true, onEnd, isBindChildDom = false } = options
          if (isBindChildDom && moveEl.children.length > 0) {
               moveEl = moveEl.firstElementChild as HTMLElement
          }

          if (!enabled) return

          // 确保元素可定位
          if (getComputedStyle(el).position === 'static') {
               el.style.position = 'absolute'
          }

          const mouseDown = (e: MouseEvent) => {
               // 阻止默认行为避免选中文本
               e.preventDefault()

               // 获取父容器
               const parentEl = el.parentElement || document.body

               // 鼠标点击位置相对于元素左上角的偏移
               const offsetX = e.clientX - el.offsetLeft
               const offsetY = e.clientY - el.offsetTop

               // 获取边界信息
               // const parentRect = parentEl.getBoundingClientRect()
               // const elRect = el.getBoundingClientRect()

               // 计算可移动范围
               const minLeft = 0
               const minTop = 0
               const maxLeft = parentEl.clientWidth - el.offsetWidth
               const maxTop = parentEl.clientHeight - el.offsetHeight

               let lastPosition = {
                    left: el.offsetLeft,
                    top: el.offsetTop,
               }

               const move = (e: MouseEvent) => {
                    // 计算新位置
                    let newLeft = e.clientX - offsetX
                    let newTop = e.clientY - offsetY

                    // 限制在父容器范围内
                    newLeft = Math.max(minLeft, Math.min(newLeft, maxLeft))
                    newTop = Math.max(minTop, Math.min(newTop, maxTop))

                    // 应用新位置
                    el.style.left = `${newLeft}px`
                    el.style.top = `${newTop}px`

                    lastPosition = { left: newLeft, top: newTop }
               }

               const mouseUp = () => {
                    document.removeEventListener('mousemove', move)
                    document.removeEventListener('mouseup', mouseUp)

                    // 拖拽结束后调用回调
                    if (onEnd) {
                         onEnd(lastPosition)
                    }
               }

               document.addEventListener('mousemove', move)
               document.addEventListener('mouseup', mouseUp)
          }

          moveEl.addEventListener('mousedown', mouseDown)
          el._moveHandler = mouseDown // 保存引用以便卸载时移除
     },

     unmounted(el: HTMLElement) {
          const moveEl = el.firstElementChild as HTMLElement
          if (moveEl && el._moveHandler) {
               moveEl.removeEventListener('mousedown', el._moveHandler)
          }
     },
}

// 扩展HTMLElement类型声明
declare global {
     interface HTMLElement {
          _moveHandler?: (e: MouseEvent) => void
     }
}

export default move
